package cn.zkdcloud.novel;

import cn.zkdcloud.core.TemplateComponent;
import org.apache.http.HttpResponse;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;

import static cn.zkdcloud.core.TemplateComponent.TemplateMessage;

import java.io.*;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import static cn.zkdcloud.novel.Novel.Chapter;

/**
 * tool
 *
 * @author zk
 * @version 2017/9/29
 */
public class NovelUtil {

    /**
     * 为了简单，发送模板消息
     */
    private static TemplateComponent templateComponent = TemplateComponent.getInstance();

    public static String NOVEL_REGEX = "最新.+<a.+href.+章.+</a>";


    public static String[] numberTable = new String[]{"零", "一", "二", "三", "四", "五", "六", "七", "八", "九", "十"};

    /**
     * novelList <latest Novel></url,latest>
     */
    public static List<Novel> novelList = new ArrayList<>();

    /**
     * the subscribe's novel of user  <novelName,userOpenIds></>
     */
    public static Map<String, List<String>> usersubscribes = new HashMap<>();


    /**
     * check is/not update
     *
     * @param novel novel
     * @return is/not
     */
    public boolean isLatest(Novel novel) {
        return isLatest(novel.getNovelUrl(), novel.getLatestChapter());
    }

    /**
     * check is/not update
     *
     * @param url           Chapter list url
     * @param latestChapter the number of latest chapter
     * @return boolean
     */
    public boolean isLatest(String url, Chapter latestChapter) {
        Chapter ret = null;
        try {
            String ChapterListContent = getContentByNovelUrl(url);//pull Chapter
            ret = findLatestChapter(ChapterListContent, url);//package
        } catch (Exception e) {
            return true;
        }

        if (latestChapter.equals(ret)) {
            latestChapter = ret;
            return true;
        } else {
            return false;
        }
    }

    /**
     * get content by novelList url
     *
     * @param url url
     * @return content
     */
    public String getContentByNovelUrl(String url) {
        String ret = "";
        HttpClient httpClient = HttpClients.createDefault();// 后悔在HttpUtil将其设成私有的
        HttpGet httpGet = new HttpGet(url);
        try {
            HttpResponse response = httpClient.execute(httpGet);
            byte[] contentBytes = EntityUtils.toByteArray(response.getEntity());
            ret = new String(contentBytes,"UTF-8");

            Matcher matcher = Pattern.compile("charset=.+\"").matcher(ret); //检查编码
            if (matcher.find()) {
                String charset = matcher.group(0).substring(8, matcher.group(0).length() - 1);
                if(charset.startsWith("\"")){
                    charset = charset.substring(1);
                }
                try {
                    ret = new String(contentBytes, charset);
                } catch (UnsupportedEncodingException e) {
                    e.printStackTrace();
                    return ret;
                }
            }
        } catch (IOException e1) {
            e1.printStackTrace();
        }
        return ret;
}

    /**
     * find the chapter of latest
     *
     * @param content ChapterListContent
     * @return number
     */
    public Chapter findLatestChapter(String content, String url) {
        Pattern pattern = Pattern.compile(NOVEL_REGEX);
        Matcher matcher = pattern.matcher(content);
        if (matcher.find()) {
            Chapter chapter = new Chapter();
            String ret = matcher.group(0);
            String originChapterUrl = ret.substring(ret.indexOf("href=\"") + 6, ret.indexOf("\">")).trim();
            String originChapterNumber = ret.substring(ret.indexOf("第") + 1, ret.indexOf("章", ret.indexOf("第"))).trim();
            String originChapterName = ret.substring(ret.indexOf(originChapterNumber) + 2 + originChapterNumber.length(), ret.indexOf("</a>")).trim();

            if (!originChapterUrl.startsWith("http")) { //chapter url
                if(originChapterUrl.startsWith("/")){//从根目录下查找
                    chapter.setChapterUrl(url.substring(0,url.indexOf("/",9)) + originChapterUrl);
                }else {
                    chapter.setChapterUrl(url.substring(0, url.lastIndexOf("/")) + originChapterUrl);
                }
            } else {
                chapter.setChapterUrl(originChapterUrl);
            }

            if (NovelUtil.isDigit(originChapterNumber)) { //chapter number
                chapter.setChapterNumber(Integer.valueOf(originChapterNumber));
            } else {
                chapter.setChapterNumber(NovelUtil.convertNumber(originChapterNumber));
            }

            chapter.setChapterName(originChapterName);//chapter name
            chapter.setChapterDate(new SimpleDateFormat("yyyy-MM-dd : hh-mm-ss").format(new Date()));
            return chapter;
        }
        return null;
    }

    /**
     * add a new novel
     *
     * @param novelName novelName
     * @param novelUrl  novelDownloadUrl
     * @throws Exception exception
     */
    public void addNovel(String novelName, String novelUrl) throws Exception {
        try {
            novelUrl.trim();
            if (novelUrl.endsWith("/")) {
                novelUrl = novelUrl.substring(0, novelUrl.length() - 1);
            }
            Novel novel = new Novel();
            novel.setNovelName(novelName);
            novel.setNovelUrl(novelUrl);
            novel.setLatestChapter(findLatestChapter(getContentByNovelUrl(novelUrl), novelUrl));
            novelList.add(novel);
        } catch (Exception e) {
            throw new Exception("fail done");
        }
    }

    /**
     * subscribe novel
     *
     * @param novelName novel name
     * @param openId    user's open id
     */
    public boolean subscribeNovel(String novelName, String openId) {
        for (Novel novel : novelList) {//check novel and subscribe
            if (novel.getNovelName().equals(novelName)) {
                usersubscribes.get(novelName).add(openId);// add subscribe to novel
                NovelUtil.pushUpdate(novel, Arrays.asList(openId));//send templateMessage to tip
                return true;
            }
        }
        return false;
    }

    /**
     * chinese to Integer
     *
     * @param number chinese number
     * @return Integer
     */
    public static Integer convertNumber(String number) {
        String ret = "";
        for (Character character : number.toCharArray()) {
            for (int i = 0; i < numberTable.length; i++) {
                if (numberTable[i].equals(character.toString())) {
                    ret += i % 10;
                }
            }
        }
        return Integer.valueOf(ret);
    }

    /**
     * judge String is/not digit
     *
     * @param number judgeNumberStr
     * @return is/not
     */
    public static boolean isDigit(String number) {
        for (Character character : number.toCharArray()) {
            if (!Character.isDigit(character)) {
                return false;
            }
        }
        return true;
    }

    /**
     * push latest chapter to users
     *
     * @param novel novel
     */
    public static void pushUpdate(Novel novel) {
        List<String> tarOpenIds = usersubscribes.get(novel.getNovelName());
        if (tarOpenIds != null && !tarOpenIds.isEmpty()) {
            pushUpdate(novel, tarOpenIds);
        }
    }

    /**
     * push latest chapter to user by openId
     *
     * @param novel   novel
     * @param openIds user openids
     */
    public static void pushUpdate(Novel novel, List<String> openIds) {
        TemplateMessage message = templateComponent.getTemplateByName("小说更新提醒");
        message.addData("novelName", novel.getNovelName(), "#44b549")
                .addData("number", String.valueOf(novel.getLatestChapter().getChapterNumber()))
                .addData("title", novel.getLatestChapter().getChapterName(), "#e03838");

        for (String openId : openIds) {
            message.setTouserAndUrl(openId, novel.getLatestChapter().getChapterUrl());
            templateComponent.sendTemplateMessage(message);
        }
    }
}
